#include <wchar.h>
#include <linux/types.h>
#include <linux/unistd.h>
#include <linux/kernel.h>
#include <linux/limits.h>
#include <linux/xattr.h>
#include "Syscall.h"
#include "System.h"

/// <summary>
/// The CreateDir function 
/// create a directory.
/// </summary>
int CreateDir(const wchar_t *path, int mode)
{
	int result = -1;
	char data[PATH_MAX];

	if (wcstombs(data, path, PATH_MAX) <= 0)
		return -1;

	if ((result = Syscall2(__NR_mkdir, (int)data, mode)) < 0)
		return -1;

	return result;
}

/// <summary>
/// The DeleteDirectory function 
/// deletes an existing empty directory.
/// </summary>
int DeleteDirectory(const wchar_t *path)
{
	int result = -1;
	char data[PATH_MAX];

	if (wcstombs(data, path, PATH_MAX) <= 0)
		return -1;

	if ((result = Syscall1(__NR_rmdir, (int)data)) < 0)
		return -1;

	return result;
}

/// <summary>
/// The Open function 
/// open and possibly create a file or device.
/// </summary>
int Open(const wchar_t *path, int flags, int mode)
{
	int result = -1;
	char data[PATH_MAX];

	if (wcstombs(data, path, PATH_MAX) <= 0)
		return -1;

	if ((result = Syscall3(__NR_open, (int)data, flags, mode)) < 0)
		return -1;

	return result;
}

/// <summary>
/// The SetOwner function 
/// change the owner or group of the
/// file specified by path. Only a privileged
/// process (Linux: one with the CAP_CHOWN capability)
/// may change the owner of a file.
/// </summary>
int SetOwner(const wchar_t *path, UID uid, GID gid)
{
	int result = -1;
	char data[PATH_MAX];

	if (wcstombs(data, path, PATH_MAX) <= 0)
		return -1;

	if ((result = Syscall3(__NR_chown, (int)data, uid, gid)) < 0)
		return -1;

	return result;
}

/// <summary>
/// The GetFileAttribute function 
/// retrieves file system attributes for
/// a specified file or directory.
/// </summary>
int GetFileAttribute(int handle, const char *name, void *value, int size)
{
	int result = -1;
	if ((result = Syscall4(__NR_fgetxattr, handle, (int)name, (int)value, size)) < 0)
		return -1;
	return result;
}

/// <summary>
/// The SetFileAttribute function 
/// sets file system attributes for a
/// specified file or directory.
/// </summary>
int SetFileAttribute(int handle, const char *name, const void *value, int size, int flags)
{
	int result = -1;
	if ((result = Syscall5(__NR_fsetxattr, handle, (int)name, (int)value, size, flags)) < 0)
		return -1;
	return result;
}

/// <summary>
/// The GetFileAttributes function 
/// retrieves file system attributes for
/// a specified file or directory.
/// </summary>
int GetFileAttributes(int handle, char *list, int size)
{
	int result = -1;
	if ((result = Syscall3(__NR_flistxattr, handle, (int)list, size)) < 0)
		return -1;
	return result;
}

/// <summary>
/// The FileLock function 
/// apply an advisory lock on an open file.
/// </summary>
int FileLock(int handle)
{
	/* LOCK_EX */
	int result = -1;
	if ((result = Syscall2(__NR_flock, handle, 2)) < 0)
		return -1;
	return result;
}

/// <summary>
/// The FileUnlock function 
/// remove an advisory lock on an open file.
/// </summary>
int FileUnlock(int handle)
{
	/* LOCK_UN */
	int result = -1;
	if ((result = Syscall2(__NR_flock, handle, 8)) < 0)
		return -1;
	return result;
}

/// <summary>
/// The Read function 
/// reads data from the specified file
/// or input/output (I/O) device.
/// </summary>
int Read(int handle, void *buffer, int count)
{
	int result = -1;
	if ((result = Syscall3(__NR_read, handle, (int)buffer, count)) < 0)
		return -1;
	return result;
}

/// <summary>
/// The Write function 
/// writes data to the specified file
/// or input/output (I/O) device.
/// </summary>
int Write(int handle, const void *buffer, int count)
{
	int result = -1;
	if ((result = Syscall3(__NR_write, handle, (int)buffer, count)) < 0)
		return -1;
	return result;
}

/// <summary>
/// The Seek function 
/// moves the file pointer of
/// the specified file.
/// </summary>
int Seek(int handle, int offset, int whence)
{
	int result = -1;
	if ((result = Syscall3(__NR_lseek, handle, offset, whence)) < 0)
		return -1;
	return result;
}

/// <summary>
/// The Duplicate function 
/// duplicate a file descriptor.
/// </summary>
int Duplicate(int handle)
{
	int result = -1;
	if ((result = Syscall1(__NR_dup, handle)) < 0)
		return -1;
	return result;
}

/// <summary>
/// The Close function 
/// close a file descriptor.
/// </summary>
int Close(int handle)
{
	int result = -1;
	if ((result = Syscall1(__NR_close, handle)) < 0)
		return -1;
	return result;
}
